first attempt at an adjacently tagged union for consideration#94
first attempt at an adjacently tagged union for consideration#94altendky wants to merge 60 commits intopython-desert:mainfrom
Conversation
Codecov Report
@@ Coverage Diff @@
## main #94 +/- ##
==========================================
Coverage 100.00% 100.00%
==========================================
Files 6 9 +3
Lines 468 820 +352
Branches 69 106 +37
==========================================
+ Hits 468 820 +352
Continue to review full report at Codecov.
|
this gives much more interesting test results where you can see the deserialization is fine due to the unique tags but the serialization is not.
src/desert/_fields.py
Outdated
|
|
||
| @attr.s(auto_attribs=True) | ||
| class TypeDictFieldRegistry: | ||
| the_dict: typing.Dict[typing.Union[type, str], marshmallow.fields.Field] = attr.ib( |
There was a problem hiding this comment.
I'm not a big the_foo user, perhaps .mapping or something.
There was a problem hiding this comment.
Heh, yeah, that was a garbage name so as to not think about it and worry about other things. Could also just be .dict
|
Oh hey... look. We can't add the |
There was a problem hiding this comment.
I need a clearer presentation of the relational properties of the Registry idea. There are several entity categories: tag, field, class, hint. For each category C, I want a list of which of the others are required to retrieve a unique instance of C. For example, "a w is uniquely identifiable from a (x,z) tuple or a (y,z) tuple" where w,x,y,z are standing in for some of {tag,field,class,hint}.
| registry.register( | ||
| hint=Cat, | ||
| tag="cat", | ||
| field=marshmallow.fields.Nested(desert.schema(Cat, meta={"ordered": True})), |
There was a problem hiding this comment.
It seems weird for a standalone class to be registered as a Nested.
There was a problem hiding this comment.
I thought this was how you made a field from a class. But yes, a person having to write this is at least questionable UX. Added to the Draft for: list in the OP.
P.S. A direct answer is at the end. This was a good refresher for myself and I leave it here in case it is useful. Copied here.
It may be that this mechanism should have a higher level of formality, but I will start by trying to explain what is already here. I think the registry protocol describes the needed functionality and then we can move on to the provided implementation. class FieldRegistryProtocol(typing_extensions.Protocol):
"""This protocol encourages registries to provide a common interface. The actual
implementation of the mapping from objects to be serialized to their Marshmallow
fields, and likewise from the serialized data, can take any form.
"""
def register(
self,
hint: t.Any,
tag: str,
field: marshmallow.fields.Field,
) -> None:
"""Inform the registry of the relationship between the passed hint, tag, and
field.
"""
...
@property
def from_object(self) -> "FromObjectProtocol":
"""This is a funny way of writing that the registry's `.from_object()` method
should satisfy :class:`FromObjectProtocol`.
"""
...
@property
def from_tag(self) -> "FromTagProtocol":
"""This is a funny way of writing that the registry's `.from_tag()` method
should satisfy :class:`FromTagProtocol`.
"""
...(I wonder if I should (could?) make a function to create those protocol-conforming methods...) class FromObjectProtocol(typing_extensions.Protocol):
def __call__(self, value: object) -> HintTagField:
...
class FromTagProtocol(typing_extensions.Protocol):
def __call__(self, tag: str) -> HintTagField:
...Once configured, the registry needs to be able to process either an object to be serialized (
So... the interface does not mandate a whole lot. You could satisfy it with random return values. That's certainly a bit extreme, but I had avoided thus far thinking through what weird corners people might find for oddball relationships between hints, tags, and fields. So, now for the provided implementation,
So I guess for now it is using just the hint to resolve a given object to a field and tag.
So I guess the summary of my self-reacquaintance with this code is that the present implementation in |
|
Thanks, I'm starting to get the picture. |
#36
Draft for:
.__origin__feature (or rather it only giveslistfortyping.Listin 3.7+)Nestedetc at https://github.com/python-desert/desert/pull/94/files#r704735427